package com.corpgovernment.travelstandard.impl;

import com.corpgovernment.api.applytrip.metadata.EApplyTripTrafficType;
import com.corpgovernment.api.organization.dto.TravelStandardRcFixRsp;
import com.corpgovernment.api.organization.dto.request.TravelStandardRcTypeReq;
import com.corpgovernment.api.travelstandard.enums.TravelStandardTypeEnum;
import com.corpgovernment.api.travelstandard.service.IMbTravelstandReasonCodeService;
import com.corpgovernment.api.travelstandard.vo.MbTravelstandReasonCodeVo;
import com.corpgovernment.api.travelstandard.vo.Node;
import com.corpgovernment.api.travelstandard.vo.RCListVo;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.base.AbstractBaseService;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.entity.db.BaseEntity;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.utils.ObjectUtils;
import com.corpgovernment.common.utils.PageUtils;
import com.corpgovernment.travelstandard.entity.db.MbTravelstandFlight;
import com.corpgovernment.travelstandard.entity.db.MbTravelstandIntlFlight;
import com.corpgovernment.travelstandard.enums.ProductTravelStandardRCEnum;
import com.corpgovernment.travelstandard.mapper.MbTravelstandFlightMapper;
import com.corpgovernment.travelstandard.mapper.MbTravelstandIntlFlightMapper;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.travelstandard.entity.db.MbTravelstandReasonCode;
import com.corpgovernment.travelstandard.mapper.MbTravelstandReasonCodeMapper;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MbTravelstandReasonCodeService extends AbstractBaseService implements IMbTravelstandReasonCodeService {

    @Autowired
    private MbTravelstandReasonCodeMapper mbTravelstandReasonCodeMapper;

    @Autowired
    private MbTravelstandFlightService travelstandFlightService;

    @Autowired
    private MbTravelstandIntlFlightService travelstandIntlFlightService;

    @Autowired
    private MbTravelstandTrainService travelstandTrainService;

    @Autowired
    private MbTravelstandHotelService travelstandHotelService;

    @Autowired
    private MbTravelstandCarService travelstandCarService;

    @Autowired
    private OrganizationApollo organizationApollo;

    @Autowired
    private MbTravelstandFlightMapper mbTravelstandFlightMapper;

    @Autowired
    private MbTravelstandIntlFlightMapper mbTravelstandIntlFlightMapper;

    @Override
    public void insert(MbTravelstandReasonCodeVo model) {
        mbTravelstandReasonCodeMapper.insertSelective(ObjectUtils.copyProperties(model, MbTravelstandReasonCode.class));
    }

    @Override
    public int delete(Long id) {
        return mbTravelstandReasonCodeMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int update(MbTravelstandReasonCodeVo model) {
        return mbTravelstandReasonCodeMapper.updateByPrimaryKeySelective(ObjectUtils.copyProperties(model, MbTravelstandReasonCode.class));
    }

    @Override
    public MbTravelstandReasonCodeVo get(Long id) {
        return ObjectUtils.copyProperties(mbTravelstandReasonCodeMapper.selectByPrimaryKey(id), MbTravelstandReasonCodeVo.class);
    }

    @Override
    public List<MbTravelstandReasonCodeVo> list(MbTravelstandReasonCodeVo model) {
        List<MbTravelstandReasonCodeVo> travelstandReasonCodeVos = new ArrayList<>();
        for (MbTravelstandReasonCode travelstandReasonCode : mbTravelstandReasonCodeMapper.list(ObjectUtils.copyProperties(model, MbTravelstandReasonCode.class))) {
            MbTravelstandReasonCodeVo travelstandReasonCodeVo = ObjectUtils.copyProperties(travelstandReasonCode, MbTravelstandReasonCodeVo.class);
            travelstandReasonCodeVos.add(travelstandReasonCodeVo);
        }
        return travelstandReasonCodeVos;
    }

    @Override
    public Page page(MbTravelstandReasonCodeVo model) {
        MbTravelstandReasonCode param = ObjectUtils.copyProperties(model, MbTravelstandReasonCode.class);
        PageContext.startPage(model.getPageNum(), model.getPageSize());
        List<MbTravelstandReasonCode> list = mbTravelstandReasonCodeMapper.list(param);
        return PageUtils.optPageBy(list, MbTravelstandReasonCodeVo.class);
    }

    @Override
    public int deleteByTsIdAndTsType(Long tsId, String tsType) {
        return mbTravelstandReasonCodeMapper.deleteByTsIdAndTsType(tsId, tsType);
    }

    /**
     * 运营端更新RC方法
     *
     * @param rcListVo
     * @return
     */
    public void updateTravelstandReasonCode(RCListVo rcListVo) {
        String id = rcListVo.getId();
        if (StringUtils.isBlank(id)) {
            throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标id不能为空!");
        }
        List<Node> rcList = rcListVo.getRcList();
        if (rcList == null || rcList.size() == 0) {
            throw new CorpBusinessException(ExceptionCodeEnum.Alert, "RC项不可为空!");
        }
        String tsType = rcListVo.getTsType();
        //判断机火酒差标是否存在
        if (TravelStandardTypeEnum.Train.getCode().equals(tsType)) {
            if (travelstandTrainService.get(Long.valueOf(id)) == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标不存在!");
            }
        } else if (TravelStandardTypeEnum.Hotel.getCode().equals(tsType)) {
            if (travelstandHotelService.get(Long.valueOf(id)) == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标不存在!");
            }
        } else if (TravelStandardTypeEnum.Flight.getCode().equals(tsType)) {
            if (travelstandFlightService.get(Long.valueOf(id)) == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标不存在!");
            }
        } else if (TravelStandardTypeEnum.IntlFlight.getCode().equals(tsType)) {
            if (travelstandIntlFlightService.get(Long.valueOf(id)) == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标不存在!");
            }
        } else if (TravelStandardTypeEnum.Car.getCode().equals(tsType)) {
            if (travelstandCarService.get(Long.valueOf(id)) == null) {
                throw new CorpBusinessException(ExceptionCodeEnum.Alert, "差标不存在!");
            }
        }
        //删除管控相关RC
        deleteByTsIdAndRcType(Long.valueOf(id), rcListVo.getRcType());
        //插入所有RC
        for (Node node : rcList) {
            MbTravelstandReasonCode travelstandReasonCode = new MbTravelstandReasonCode();
            travelstandReasonCode.setTsRcType(rcListVo.getRcType());
            travelstandReasonCode.setTsType(rcListVo.getTsType());
            travelstandReasonCode.setTsId(Long.valueOf(id));
            travelstandReasonCode.setName(node.getName());
            travelstandReasonCode.setIsChecked(node.getIsChecked());
//            if (!StringUtils.isBlank(node.getId())) {
//                travelstandReasonCode.setId(Long.valueOf(node.getId()));
//            }
            mbTravelstandReasonCodeMapper.insertSelective(travelstandReasonCode);
        }
    }

    public int deleteByTsIdAndRcType(Long tsId, String rcType) {
        return mbTravelstandReasonCodeMapper.deleteByTsIdAndRcType(tsId, rcType);
    }

    /**
     * 为旧 RC数据添加新差标 RC信息
     * @param request
     * @return
     */
    public TravelStandardRcFixRsp addOldTravelStandardRcInfo(TravelStandardRcTypeReq request) {
        //1 参数校验
        Integer productType = request.getProductType();
        String rcTravelStandardTemp = request.getRcTravelStandardTemp();
        String tsRcType = request.getTsRcType();
        ProductTravelStandardRCEnum rcEnum = ProductTravelStandardRCEnum.getByProductCode(productType);
        String tsType = rcEnum.getTsType();
        if (Objects.isNull(productType) || StringUtils.isBlank(rcTravelStandardTemp) || StringUtils.isBlank(tsRcType) || Objects.isNull(rcEnum) ) {
            return null;
        }
        TravelStandardRcFixRsp travelStandardRcFixRsp = new TravelStandardRcFixRsp();
        //2 从Apollo获取全产线RC信息
        Map rcTemplate = JsonUtils.parseMap(organizationApollo.getAllProductRcReasonTemplate());
        if (Objects.isNull(rcTemplate)) {
            return null;
        }
        if (rcTemplate.containsKey(rcTravelStandardTemp)) {
            List<MbTravelstandReasonCodeVo> travelStandardReasonCodeVosFc = JsonUtils.parseArray(JsonUtils.toJsonString(rcTemplate.get(rcTravelStandardTemp)), MbTravelstandReasonCodeVo.class);
            if (CollectionUtils.isEmpty(travelStandardReasonCodeVosFc)) {
                return null;
            }
            //3 根据新增的tsRcType，查询旧数据中新增管控类型的RC信息（在表mb_travelstand_reason_code中 tsId和tsRcType 才能确定具体的差标）
            Example example = new Example(MbTravelstandReasonCode.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("tsType", tsType);
            List<MbTravelstandReasonCode> mbTravelstandReasonCodes = mbTravelstandReasonCodeMapper.selectByExample(example);
            //4 获取 表mb_travelstand_reason_code中当前产线的全部差标ID
            List<Long> currProductTsIdList = mbTravelstandReasonCodes.stream().map(MbTravelstandReasonCode::getTsId).distinct().collect(Collectors.toList());
            //5 获取 已拥有RC信息的 新增的管控类型 的差标ID (已拥有RC信息的差标则不再插入RC信息)
            Set<Long> ownFreshTypeTsIdSet = mbTravelstandReasonCodes.stream().filter(info -> (Objects.equals(tsRcType, info.getTsRcType()))).map(MbTravelstandReasonCode::getTsId).collect(Collectors.toSet());
            //6 为每个差标批量插入RC信息
            for (Long travelStandardId : currProductTsIdList) {
                //已拥有RC信息的差标则不再插入新TsType的RC信息
                if (ownFreshTypeTsIdSet.contains(travelStandardId)){
                    continue;
                }
                // 已拥有新增的管控类型的RC信息的差标则不再插入
                List<MbTravelstandReasonCode> mbTravelStandardReasonCodes = new ArrayList<>();
                for (MbTravelstandReasonCodeVo travelStandardRcVo : travelStandardReasonCodeVosFc) {
                    travelStandardRcVo.setTsId(travelStandardId);
                    MbTravelstandReasonCode mbTravelstandReasonCode = ObjectUtils.copyProperties(travelStandardRcVo, MbTravelstandReasonCode.class);
                    if (Objects.nonNull(mbTravelstandReasonCode)) {
                        mbTravelstandReasonCode.setDatachangeCreatetime(new Date());
                        mbTravelstandReasonCode.setDatachangeLasttime(new Date());
                        mbTravelStandardReasonCodes.add(mbTravelstandReasonCode);
                    }
                }
                if (CollectionUtils.isNotEmpty(mbTravelStandardReasonCodes)) {
                    log.info("mbTravelStandardReasonCodes:{}", mbTravelStandardReasonCodes);
                    mbTravelstandReasonCodeMapper.insertList(mbTravelStandardReasonCodes);
                }
            }
            travelStandardRcFixRsp.setTravelStandardIdList(currProductTsIdList);
        }
        return travelStandardRcFixRsp;
    }

}
